﻿using System;
using System.Collections;
using System.Xml;
using System.Text;
using System.Web;
using InfoJetSoft.Service.Entity;
using InfoJetSoft.Service.Util;

namespace InfoJetSoft.Service.Worker
{
	//分析DataAdapter.
	class XSNManifestDataAdapterParseWorker
	{
		//ParseDataAdapterList在XSNManifestLoadWorker中调用.
		//用于获取Manfiest中的所有DataAdapter,形成List,主要用于ManagedCode.DataAdapters中.
		public static void parseDataAdapterList(HttpContext context, Manifest manifest)
		{
			XmlElement root = manifest.Doc.DocumentElement;
			string xsfPrefix = manifest.XsfPrefix;
			
			string adoAdapterName = NamespaceUtil.toFullName( xsfPrefix, "adoAdapter" );
			string xmlFileAdapterName = NamespaceUtil.toFullName( xsfPrefix, "xmlFileAdapter" );
			string webServiceAdapterName = NamespaceUtil.toFullName( xsfPrefix, "webServiceAdapter" );
			string sharepointListAdapterName = NamespaceUtil.toFullName( xsfPrefix, "sharepointListAdapter" );
			string davAdapterName = NamespaceUtil.toFullName( xsfPrefix, "davAdapter" );
			string emailAdapterName = NamespaceUtil.toFullName( xsfPrefix, "emailAdapter" );
			string submitToHostAdapterName = NamespaceUtil.toFullName( xsfPrefix, "submitToHostAdapter" );

			ArrayList dataAdapterList = new ArrayList();

			//实际上,这里的dataAdapter是用于备份目的,一般没有实际用途.
			string dataAdaptersFilter = "//" + NamespaceUtil.toFullName( xsfPrefix, "dataAdapters" ) + "/*";
			XmlNodeList dataAdapterElementList = DOMUtil.selectNodes(root, dataAdaptersFilter, 0, manifest.NsResolver);
			foreach( XmlElement dataAdapterElement in dataAdapterElementList )
			{
				object dataAdapter = null;
				if( dataAdapterElement.Name.Equals( adoAdapterName ) )
				{
					dataAdapter = XSNManifestDataAdapterParseWorker.parseAdoAdapter( manifest, dataAdapterElement );
				}
				else if( dataAdapterElement.Name.Equals( xmlFileAdapterName ) )
				{
					dataAdapter = XSNManifestDataAdapterParseWorker.parseFileAdapter( manifest, dataAdapterElement );
				}
				else if( dataAdapterElement.Name.Equals( webServiceAdapterName ) )
				{
					dataAdapter = XSNManifestDataAdapterParseWorker.parseWSAdapter( context, manifest, dataAdapterElement );
				}
				else if( dataAdapterElement.Name.Equals( sharepointListAdapterName ) )
				{
					dataAdapter = XSNManifestDataAdapterParseWorker.parseSPListAdapter( manifest, dataAdapterElement );
				}
				else if( dataAdapterElement.Name.Equals( davAdapterName ) )
				{
					dataAdapter = XSNManifestDataAdapterParseWorker.parseDavAdapter( manifest, dataAdapterElement );
				}
				else if( dataAdapterElement.Name.Equals( emailAdapterName ) )
				{
					dataAdapter = XSNManifestDataAdapterParseWorker.parseEmailAdapter( manifest, dataAdapterElement );
				}
				else if( dataAdapterElement.Name.Equals( submitToHostAdapterName ) )
				{
					dataAdapter = XSNManifestDataAdapterParseWorker.parseSubmitToHostAdapter( manifest, dataAdapterElement );
				}
				if( dataAdapter != null )
				{
					dataAdapterList.Add( dataAdapter );
				}
			}

			//将DataObject,Query,Submit中的DataAdapter添加dataAdapterList中:
			foreach( DataObject dataObject in manifest.DataObjectList )
			{
				if( dataObject.AdoAdapter != null )
				{
					dataAdapterList.Add( dataObject.AdoAdapter );
				}
				if( dataObject.FileAdapter != null )
				{
					dataAdapterList.Add( dataObject.FileAdapter );
				}
				if( dataObject.SPListAdapter != null )
				{
					dataAdapterList.Add( dataObject.SPListAdapter );
				}
				if( dataObject.WSAdapter != null )
				{
					dataAdapterList.Add( dataObject.WSAdapter );
				}
			}
			
			if( manifest.Query != null )
			{
				if( manifest.Query.AdoAdapter != null )
				{
					dataAdapterList.Add( manifest.Query.AdoAdapter );
				}
				if( manifest.Query.FileAdapter != null )
				{
					dataAdapterList.Add( manifest.Query.FileAdapter );
				}
				if( manifest.Query.SPListAdapter != null )
				{
					dataAdapterList.Add( manifest.Query.SPListAdapter );
				}
				if( manifest.Query.WSAdapter != null )
				{
					dataAdapterList.Add( manifest.Query.WSAdapter );
				}
			}

			if( manifest.Submit != null )
			{
				if( manifest.Submit.AdoAdapter != null )
				{
					dataAdapterList.Add( manifest.Submit.AdoAdapter );
				}
				if( manifest.Submit.DavAdapter != null )
				{
					dataAdapterList.Add( manifest.Submit.DavAdapter );
				}
				if( manifest.Submit.EmailAdapter != null )
				{
					dataAdapterList.Add( manifest.Submit.EmailAdapter );
				}
				if( manifest.Submit.WSAdapter != null )
				{
					dataAdapterList.Add( manifest.Submit.WSAdapter );
				}
				if( manifest.Submit.SubmitToHostAdapter != null )
				{
					dataAdapterList.Add( manifest.Submit.SubmitToHostAdapter );
				}
			}

			manifest.DataAdapterList = dataAdapterList;
		}

		//根据DataAdapter名字查找DataAdapter.
		public static object findDataAdapterByName(Manifest manifest, string dataAdapterName)
		{
			foreach( object dataAdapter in manifest.DataAdapterList )
			{
				if( dataAdapter is SubmitToHostAdapter )
				{
					SubmitToHostAdapter submitToHostAdapter = (SubmitToHostAdapter) dataAdapter;
					if( submitToHostAdapter.Name != null && submitToHostAdapter.Name.Equals( dataAdapterName ) )
					{
						return submitToHostAdapter;
					}
				}
				if( dataAdapter is DataEmailAdapter )
				{
					DataEmailAdapter emailAdapter = (DataEmailAdapter) dataAdapter;
					if( emailAdapter.Name != null && emailAdapter.Name.Equals( dataAdapterName ) )
					{
						return emailAdapter;
					}
				}
				else if( dataAdapter is DataDavAdapter )
				{
					DataDavAdapter davAdapter = (DataDavAdapter) dataAdapter;
					if( davAdapter.Name != null && davAdapter.Name.Equals( dataAdapterName ) )
					{
						return davAdapter;
					}
				}
				else if( dataAdapter is DataWSAdapter )
				{
					DataWSAdapter wsAdapter = (DataWSAdapter) dataAdapter;
					if( wsAdapter.Name != null && wsAdapter.Name.Equals( dataAdapterName ) )
					{
						return wsAdapter;
					}
				}
				else if( dataAdapter is DataADOAdapter )
				{
					DataADOAdapter adoAdapter = (DataADOAdapter) dataAdapter;
					if( adoAdapter.Name != null && adoAdapter.Name.Equals( dataAdapterName ) )
					{
						return adoAdapter;
					}
				}
				else if( dataAdapter is DataFileAdapter )
				{
					DataFileAdapter fileAdapter = (DataFileAdapter) dataAdapter;
					if( fileAdapter.Name != null && fileAdapter.Name.Equals( dataAdapterName ) )
					{
						return fileAdapter;
					}
				}
				else if( dataAdapter is DataSPListAdapter )
				{
					DataSPListAdapter spListAdapter = (DataSPListAdapter) dataAdapter;
					if( spListAdapter.Name != null && spListAdapter.Name.Equals( dataAdapterName ) )
					{
						return spListAdapter;
					}
				}
			}
			return null;
		}

		//分析容器元素中的xsf:xxxAdapter.这里useQueryAdapter是个特例,实际上它也相当与引用一个Adapter.
		//它们与useScriptHandler,submitToHostAdapter和useHttpHandler是不同的,后三者不出现在ManagedCode.DataAdapters中.
		public static object parseDataAdapterInContainer( HttpContext context, Manifest manifest, XmlElement containerElement )
		{
			string xsfPrefix = manifest.XsfPrefix;

			string adoFilter = NamespaceUtil.toFullName(xsfPrefix, "adoAdapter");
			XmlElement adoAdapterElement = (XmlElement) DOMUtil.selectANode( containerElement, adoFilter, manifest.NsResolver );
			if( adoAdapterElement != null )
			{
				return parseAdoAdapter( manifest, adoAdapterElement );
			}	

			string xmlFileFilter = NamespaceUtil.toFullName(xsfPrefix, "xmlFileAdapter");
			XmlElement fileAdapterElement = (XmlElement) DOMUtil.selectANode( containerElement, xmlFileFilter, manifest.NsResolver );
			if( fileAdapterElement != null )
			{
				return parseFileAdapter( manifest, fileAdapterElement );
			}

			string wsFilter = NamespaceUtil.toFullName(xsfPrefix, "webServiceAdapter");
			XmlElement wsAdapterElement = (XmlElement) DOMUtil.selectANode( containerElement, wsFilter, manifest.NsResolver );
			if( wsAdapterElement != null )
			{
				return parseWSAdapter( context, manifest, wsAdapterElement );
			}

			string spListFilter = NamespaceUtil.toFullName(xsfPrefix, "sharepointListAdapter");
			XmlElement spListAdapterElement = (XmlElement) DOMUtil.selectANode( containerElement, spListFilter, manifest.NsResolver );
			if( spListAdapterElement != null )
			{
				return parseSPListAdapter( manifest, spListAdapterElement );
			}

            //CID 0703 //2010.12.19 //Begin
            string spListRWFilter = NamespaceUtil.toFullName(xsfPrefix, "sharepointListAdapterRW");
            XmlElement spListRWAdapterElement = (XmlElement)DOMUtil.selectANode(containerElement, spListRWFilter, manifest.NsResolver);
            if (spListRWAdapterElement != null)
            {
                return parseSPListRWAdapter(manifest, spListRWAdapterElement);
            }
            //CID 0703 //2010.12.19 //End

			string davFilter = NamespaceUtil.toFullName(xsfPrefix, "davAdapter");
			XmlElement davAdapterElement = (XmlElement) DOMUtil.selectANode( containerElement, davFilter, manifest.NsResolver );
			if( davAdapterElement != null )
			{
				return parseDavAdapter( manifest, davAdapterElement );
			}

			string emailFilter = NamespaceUtil.toFullName(xsfPrefix, "emailAdapter");
			XmlElement emailAdapterElement = (XmlElement) DOMUtil.selectANode( containerElement, emailFilter, manifest.NsResolver );
			if( emailAdapterElement != null )
			{
				return parseEmailAdapter( manifest, emailAdapterElement );
			}

			string submitToHostAdapterFilter = NamespaceUtil.toFullName(xsfPrefix, "submitToHostAdapter");
			XmlElement submitToHostAdapterElement = (XmlElement)DOMUtil.selectANode( containerElement, submitToHostAdapterFilter, manifest.NsResolver );
			if( submitToHostAdapterElement != null )
			{
				return parseSubmitToHostAdapter( manifest, submitToHostAdapterElement );
			}

			string useQueryFilter = NamespaceUtil.toFullName(xsfPrefix, "useQueryAdapter");
			XmlElement useQueryElement = (XmlElement) DOMUtil.selectANode( containerElement, useQueryFilter, manifest.NsResolver );
			if( useQueryElement != null )
			{
				return new DataUseQueryAdapter();
			}

			return null;
		}

		private static SubmitToHostAdapter parseSubmitToHostAdapter( Manifest manifest, XmlElement submitToHostAdapterElement )
		{
			SubmitToHostAdapter submitToHostAdapter = new SubmitToHostAdapter();
			submitToHostAdapter.Name = submitToHostAdapterElement.GetAttribute( "name" );
			string submitAllowed = submitToHostAdapterElement.GetAttribute( "submitAllowed" );
			if( submitAllowed != null && submitAllowed.ToLower().Equals( "yes" )  )
			{
				submitToHostAdapter.SubmitAllowed = true;
			}
			
			return submitToHostAdapter;
		}

		private static DataEmailAdapter parseEmailAdapter( Manifest manifest, XmlElement emailAdapterElement )
		{
			string xsfPrefix = manifest.XsfPrefix;

			DataEmailAdapter emailAdapter = new DataEmailAdapter();

			emailAdapter.Name = getAdapterName( emailAdapterElement );
			emailAdapter.QueryAllowed = getAdapterQueryAllowed( emailAdapterElement );
			emailAdapter.SubmitAllowed = getAdapterSubmitAllowed( emailAdapterElement );

			string toFilter = NamespaceUtil.toFullName( xsfPrefix, "to" );
			XmlElement toElement = (XmlElement)DOMUtil.selectANode( emailAdapterElement, toFilter, manifest.NsResolver );
			if( toElement != null )
			{
				string toValue = toElement.GetAttribute( "value" );
				if( toValue == null || toValue.Length <= 0 )
				{
					throw new InfoJetException( "No to value", "XDOP20" );
				}
				emailAdapter.ToValue = toValue;
				string toValueType = toElement.GetAttribute( "valueType" );
				if( toValueType == null || toValueType.Length <= 0 )
				{
					emailAdapter.ToValueType = DataEmailAdapter.Literal;
				}
				else
				{
					if( toValueType.Equals( DataEmailAdapter.Expression ) )
					{
						emailAdapter.ToValueType = DataEmailAdapter.Expression;
					}
					else
					{
						emailAdapter.ToValueType = DataEmailAdapter.Literal;
					}
				}
			}

			string ccFilter = NamespaceUtil.toFullName( xsfPrefix, "cc" );
			XmlElement ccElement = (XmlElement)DOMUtil.selectANode( emailAdapterElement, ccFilter, manifest.NsResolver );
			if( ccElement != null )
			{
				string ccValue = ccElement.GetAttribute( "value" );
				if( ccValue == null || ccValue.Length <= 0 )
				{
					throw new InfoJetException( "No cc value", "XDOP21" );
				}
				emailAdapter.CcValue = ccValue;
				string ccValueType = ccElement.GetAttribute( "valueType" );
				if( ccValueType == null || ccValueType.Length <= 0 )
				{
					emailAdapter.CcValueType = DataEmailAdapter.Literal;
				}
				else
				{
					if( ccValueType.Equals( DataEmailAdapter.Expression ) )
					{
						emailAdapter.CcValueType = DataEmailAdapter.Expression;
					}
					else
					{
						emailAdapter.CcValueType = DataEmailAdapter.Literal;
					}
				}
			}
			
			string bccFilter = NamespaceUtil.toFullName( xsfPrefix, "bcc" );
			XmlElement bccElement = (XmlElement)DOMUtil.selectANode( emailAdapterElement, bccFilter, manifest.NsResolver );
			if( bccElement != null )
			{
				string bccValue = bccElement.GetAttribute( "value" );
				if( bccValue == null || bccValue.Length <= 0 )
				{
					throw new InfoJetException( "No bcc value", "XDOP21" );
				}
				emailAdapter.BccValue = bccValue;
				string bccValueType = bccElement.GetAttribute( "valueType" );
				if( bccValueType == null || bccValueType.Length <= 0 )
				{
					emailAdapter.BccValueType = DataEmailAdapter.Literal;
				}
				else
				{
					if( bccValueType.Equals( DataEmailAdapter.Expression ) )
					{
						emailAdapter.BccValueType = DataEmailAdapter.Expression;
					}
					else
					{
						emailAdapter.BccValueType = DataEmailAdapter.Literal;
					}
				}
			}

			string subjectFilter = NamespaceUtil.toFullName( xsfPrefix, "subject" );
			XmlElement subjectElement = (XmlElement)DOMUtil.selectANode( emailAdapterElement, subjectFilter, manifest.NsResolver );
			if( subjectElement != null )
			{
				string subjectValue = subjectElement.GetAttribute( "value" );
				if( subjectValue == null || subjectValue.Length <= 0 )
				{
					throw new InfoJetException( "No subject value", "XDOP22" );
				}
				emailAdapter.SubjectValue = subjectValue;
				string subjectValueType = subjectElement.GetAttribute( "valueType" );
				if( subjectValueType == null || subjectValueType.Length <= 0 )
				{
					emailAdapter.SubjectValueType = DataEmailAdapter.Literal;
				}
				else
				{
					if( subjectValueType.Equals( DataEmailAdapter.Expression ) )
					{
						emailAdapter.SubjectValueType = DataEmailAdapter.Expression;
					}
					else
					{
						emailAdapter.SubjectValueType = DataEmailAdapter.Literal;
					}
				}
			}

			string attachFilter = NamespaceUtil.toFullName( xsfPrefix, "attachmentFileName" );
			XmlElement attachElement = (XmlElement)DOMUtil.selectANode( emailAdapterElement, attachFilter, manifest.NsResolver );
			if( attachElement != null )
			{
				string attachValue = attachElement.GetAttribute( "value" );
				if( attachValue == null || attachValue.Length <= 0 )
				{
					throw new InfoJetException( "No attachmentFileName value", "XDOP22" );
				}
				emailAdapter.AttachmentFileNameValue = attachValue;
				string attachValueType = attachElement.GetAttribute( "valueType" );
				if( attachValueType == null || attachValueType.Length <= 0 )
				{
					emailAdapter.AttachmentFileNameValueType = DataEmailAdapter.Literal;
				}
				else
				{
					if( attachValueType.Equals( DataEmailAdapter.Expression ) )
					{
						emailAdapter.AttachmentFileNameValueType = DataEmailAdapter.Expression;
					}
					else
					{
						emailAdapter.AttachmentFileNameValueType = DataEmailAdapter.Literal;
					}
				}
			}

			string introFilter = NamespaceUtil.toFullName( xsfPrefix, "intro" );
			XmlElement introElement = (XmlElement)DOMUtil.selectANode( emailAdapterElement, introFilter, manifest.NsResolver );
			if( introElement != null ){
				string introValue = introElement.GetAttribute( "value" );
				if( introValue == null || introValue.Length <= 0 ){
					throw new InfoJetException( "No intro value", "XDOP23" );
				}
				emailAdapter.IntroValue = introValue;
			}

			emailAdapter.IsEmailAttachmentTypeNone = isEmailAttachmentTypeNone( manifest, emailAdapter.Name );

			return emailAdapter;
		}

		private static bool isEmailAttachmentTypeNone( Manifest manifest, string emailAdapterName )
		{
			string xsfPrefix = manifest.XsfPrefix;
			string xsf2Prefix = manifest.Doc.DocumentElement.GetPrefixOfNamespace( "http://schemas.microsoft.com/office/infopath/2006/solutionDefinition/extensions" );

			string filter = NamespaceUtil.toFullName( xsfPrefix, "extensions" );
			filter += "/" + NamespaceUtil.toFullName( xsfPrefix, "extension" );
			filter += "/" + NamespaceUtil.toFullName( xsf2Prefix, "solutionDefinition" );
			filter += "/" + NamespaceUtil.toFullName( xsf2Prefix, "dataConnections" );
			filter += "/" + NamespaceUtil.toFullName( xsf2Prefix, "emailAdapterExtension" );

            //CID 1184 //2012.04.28 //Begin
			XmlNodeList emailAdapterExtensionElementList = DOMUtil.selectNodes( manifest.Doc.DocumentElement, filter, 0, manifest.NsResolver );
            foreach (XmlElement emailAdapterExtensionElement in emailAdapterExtensionElementList)
			{
				string refName = emailAdapterExtensionElement.GetAttribute( "ref" );
				if( refName != null && refName.Equals( emailAdapterName ) )
				{
					string type = emailAdapterExtensionElement.GetAttribute( "emailAttachmentType" );
					if( type != null && type.Equals( "none" ) )
					{
						return true;
					}
				}
			}
            //CID 1184 //2012.04.28 //End
			return false;
		}

		private static DataDavAdapter parseDavAdapter( Manifest manifest, XmlElement davAdapterElement )
		{
			string xsfPrefix = manifest.XsfPrefix;

			DataDavAdapter davAdapter = new DataDavAdapter();

			davAdapter.Name = getAdapterName( davAdapterElement );
			davAdapter.QueryAllowed = getAdapterQueryAllowed( davAdapterElement );
			davAdapter.SubmitAllowed = getAdapterSubmitAllowed( davAdapterElement );

			string overwriteAllowedValue = davAdapterElement.GetAttribute( "overwriteAllowed" );
			if( overwriteAllowedValue == null || overwriteAllowedValue.Length <= 0 )
			{
				davAdapter.OverwriteAllowed = true;
			}
			else{
				if( overwriteAllowedValue.Equals( "yes" ) )
				{
					davAdapter.OverwriteAllowed = true;
				}
				else{
					davAdapter.OverwriteAllowed = false;
				}
			}

			string folderURLFilter = NamespaceUtil.toFullName( xsfPrefix, "folderURL" );
			XmlElement folderURLElement = (XmlElement)DOMUtil.selectOneNode( davAdapterElement, folderURLFilter, manifest.NsResolver );
			string folderURLValue = folderURLElement.GetAttribute( "value" );
			if( folderURLValue == null || folderURLValue.Length <= 0 )
			{
				throw new InfoJetException( "No folderURL value", "XDOP18" );
			}
			if( !(folderURLValue.EndsWith( "/" ) || folderURLValue.EndsWith( "\\" )) ){
				folderURLValue = folderURLValue + "/";
			}
			davAdapter.FolderURLValue = folderURLValue;
			
			string fileNameFilter = NamespaceUtil.toFullName( xsfPrefix, "fileName" );
			XmlElement fileNameElement = (XmlElement)DOMUtil.selectOneNode( davAdapterElement, fileNameFilter, manifest.NsResolver );
			string fileNameValue = fileNameElement.GetAttribute( "value" );
			if( fileNameValue == null || fileNameValue.Length <= 0 )
			{
				throw new InfoJetException( "No fileName value", "XDOP19" );
			}
			davAdapter.FileNameValue = fileNameValue;

			string fileNameValueType = fileNameElement.GetAttribute( "valueType" );
			if( fileNameValueType == null || fileNameValueType.Length <= 0 )
			{
				davAdapter.FileNameValueType = DataDavAdapter.Literal;
			}
			else{
				if( fileNameValueType.Equals( DataDavAdapter.Expression ) )
				{
					davAdapter.FileNameValueType = DataDavAdapter.Expression;
				}
				else
				{
					davAdapter.FileNameValueType = DataDavAdapter.Literal;
				}
			}

			return davAdapter;
		}

		private static DataWSAdapter parseWSAdapter( HttpContext context, Manifest manifest, XmlElement wsAdapterElement ){
			string xsfPrefix = manifest.XsfPrefix;

			DataWSAdapter wsAdapter = new DataWSAdapter();

			wsAdapter.Name = getAdapterName( wsAdapterElement );
			wsAdapter.QueryAllowed = getAdapterQueryAllowed( wsAdapterElement );
			wsAdapter.SubmitAllowed = getAdapterSubmitAllowed( wsAdapterElement );

			string wsdlUrl = wsAdapterElement.GetAttribute( "wsdlUrl" );
			if( wsdlUrl == null || wsdlUrl.Length <= 0 ){
				throw new InfoJetException("No wsAdapter wsdlUrl", "XDOP14");
			}
			wsAdapter.WsdlUrl = wsdlUrl; //实际上在表单运行中并不需要WsdlUrl,只是在表单代码里需要作为属性暴露出来. //CID 0027 //2008.06.20 //comment

			string useDataSet = wsAdapterElement.GetAttribute( "useDataSet" );
			if( useDataSet != null && useDataSet.Equals( "yes" ) )
			{
				wsAdapter.UseDataSet = true;
			}

			string operationFilter = NamespaceUtil.toFullName( xsfPrefix, "operation" );
			XmlElement operationElement = (XmlElement)DOMUtil.selectOneNode( wsAdapterElement, operationFilter, manifest.NsResolver );
			
			string operationName = operationElement.GetAttribute( "name" );
			if( operationName == null || operationName.Length <= 0 ){
				throw new InfoJetException( "No wsAdapter operation name", "XDOP17" );
			}
			wsAdapter.OperationName = operationName;
			
			string serviceUrl = operationElement.GetAttribute( "serviceUrl" );
			if( serviceUrl == null || serviceUrl.Length <= 0 ){
				throw new InfoJetException( "No wsAdapter serviceUrl", "XDOP15" );
			}
			//CID 0242 //2009.03.10 //Begin
			string globalWSHost = ConfigUtil.GlobalWSHost();
			if( globalWSHost != null )
			{
                //CID 0625 //2010.07.08 //Begin
                string excludedMatchPattern = ConfigUtil.GlobalWSHostExcludedMatchPattern();
                if (excludedMatchPattern == null)
                {
                    Uri serviceUri = new Uri(serviceUrl);
                    serviceUrl = globalWSHost + serviceUri.AbsolutePath;
                }
                else
                {
                    if (!System.Text.RegularExpressions.Regex.IsMatch(serviceUrl, excludedMatchPattern))
                    {
                        Uri serviceUri = new Uri(serviceUrl);
                        serviceUrl = globalWSHost + serviceUri.AbsolutePath;
                    }
                }
                //CID 0625 //2010.07.08 //End
			}
			//CID 0242 //2009.03.10 //End
            //CID 0833 //2011.03.21 //Begin
            string globalWSPath = ConfigUtil.GlobalWSPath();
            if (globalWSPath != null)
            {
                if (!(globalWSPath.EndsWith("/") || globalWSPath.EndsWith("\\")))
                {
                    globalWSPath = globalWSPath + "/";
                }
                string excludedMatchPattern = ConfigUtil.GlobalWSPathExcludedMatchPattern();
                if (excludedMatchPattern == null)
                {
                    Uri serviceUri = new Uri(serviceUrl);
                    serviceUrl = globalWSPath + serviceUri.Segments[serviceUri.Segments.Length - 1] + serviceUri.Query;
                }
                else
                {
                    if (!System.Text.RegularExpressions.Regex.IsMatch(serviceUrl, excludedMatchPattern))
                    {
                        Uri serviceUri = new Uri(serviceUrl);
                        serviceUrl = globalWSPath + serviceUri.Segments[serviceUri.Segments.Length - 1] + serviceUri.Query;
                    }
                }
            }
            //CID 0833 //2011.03.21 //End
			string customServiceUrl = manifest.FormConfiguration.GetCustomWebServiceUrl( wsAdapter.Name );
			if( customServiceUrl != null )
			{
				//CID 0139 //2008.10.09 //Begin
				if( customServiceUrl.StartsWith( "~" ) )
				{
					customServiceUrl = customServiceUrl.Replace( "~", PathUtil.getBasePath( context ) );
				}
				//CID 0139 //2008.10.09 //End
				wsAdapter.ServiceUrl = customServiceUrl;
			}
			else
			{
				wsAdapter.ServiceUrl = serviceUrl;
			}

			string soapAction = operationElement.GetAttribute( "soapAction" );
			//CID 0481 //2009.12.27 //Begin
			if( soapAction == null ){
				throw new InfoJetException( "No wsAdapter soapAction", "XDOP16" ) ;
			}
			//CID 0481 //2009.12.27 //End
			wsAdapter.SoapAction = soapAction;

			DataInput input = parseDataInputInContainer( manifest, operationElement );
			if( input != null ){
				wsAdapter.Input = input;
				XmlDocument sourceDoc = DOMUtil.buildDoc( input.SourceContent );
				wsAdapter.SoapPrefix = parseSoapPrefix( wsAdapter, sourceDoc );
			}else{
				//parse query or submit.
				wsAdapter.SoapPrefix = parseSoapPrefix( wsAdapter, manifest.Template.Doc );
			}

			return wsAdapter;
		}

		private static DataADOAdapter parseAdoAdapter( Manifest manifest, XmlElement adoAdapterElement ){
			string xsfPrefix = manifest.XsfPrefix;
			
			DataADOAdapter adoAdapter = new DataADOAdapter();

			adoAdapter.Name = getAdapterName( adoAdapterElement );
			adoAdapter.QueryAllowed = getAdapterQueryAllowed( adoAdapterElement );
			adoAdapter.SubmitAllowed = getAdapterSubmitAllowed( adoAdapterElement );

			string connectionString = adoAdapterElement.GetAttribute( "connectionString" );
			if( connectionString == null || connectionString.Length <= 0 ){
				throw new InfoJetException("No adoAdapter connectionString", "XDOP03");
			}
			adoAdapter.ConnectionString = connectionString;
			//如果存在GlobalConnectionString，统一替换为GlobalConnectionString
			string globalConnectionString = ConfigUtil.GlobalConnectionString();
			if( globalConnectionString != null )
			{
				adoAdapter.ConnectionString = globalConnectionString;
			}
			//如果存在InfoJetContext.TemplateConnectionString，统一替换为TemplateConnectionString，优先于GlobalConnectionString
			if( manifest.JetContext != null )
			{
				if( manifest.JetContext.TemplateConnectionString != null )
				{
					adoAdapter.ConnectionString = manifest.JetContext.TemplateConnectionString;
				}
			}
			string commandText = adoAdapterElement.GetAttribute( "commandText" );
			if( commandText == null || commandText.Length <= 0 ){
				throw new InfoJetException("No adoAdapter commandText", "XDOP04");
			}
			adoAdapter.CommandText = commandText;
			adoAdapter.DBSelectCommandList = DBSelectCommand.parseDBSelectCommand( adoAdapter.CommandText );
			if( adoAdapter.DBSelectCommandList != null && adoAdapter.DBSelectCommandList.Count >= 1 )
			{
				DBSelectCommand mainSelectCommand = (DBSelectCommand)adoAdapter.DBSelectCommandList[ 0 ];
				adoAdapter.TableName = mainSelectCommand.TableName;
			}

			if( adoAdapter.TableName == null || adoAdapter.TableName.Length <= 0 ){
				throw new InfoJetException("Cannot parse tableName: " + adoAdapter.CommandText, "XDOP041");
			}
			if( adoAdapter.CommandText.ToLower().StartsWith( "shape" ) ){
				//CID 0170 //2008.12.21 //Begin
				if( adoAdapter.ConnectionString.StartsWith( "Provider=msdaora;" ) )
				{
					adoAdapter.ConnectionString = adoAdapter.ConnectionString + ";PROVIDER=MSDataShape;DATA PROVIDER=msdaora;";
				}
				else if( adoAdapter.ConnectionString.StartsWith( "Driver={Microsoft ODBC for Oracle};" ) )
				{
					throw new InfoJetException( "Microsoft ODBC for Oracle is not supported.", "XDOP20" );
				}
				//CID 0170 //2008.12.21 //End
				else
				{
					adoAdapter.ConnectionString = adoAdapter.ConnectionString + ";PROVIDER=MSDataShape;DATA PROVIDER=SQLOLEDB;";
				}
			}
			return adoAdapter;
		}

		private static DataFileAdapter parseFileAdapter( Manifest manifest, XmlElement fileAdapterElement ){
			DataFileAdapter fileAdapter = new DataFileAdapter();

			fileAdapter.Name = getAdapterName( fileAdapterElement );
			fileAdapter.QueryAllowed = getAdapterQueryAllowed( fileAdapterElement );
			fileAdapter.SubmitAllowed = getAdapterSubmitAllowed( fileAdapterElement );

			string fileUrl = fileAdapterElement.GetAttribute( "fileUrl" );
			if( fileUrl == null || fileUrl.Length <= 0 ){
				throw new InfoJetException("No xmlFileAdapter fileUrl", "XDOP06");
			}
			fileAdapter.FileUrl = fileUrl;

			//CID 0540 //2010.04.21 //https
			string lowerFileUrl = fileAdapter.FileUrl.ToLower();
			if( lowerFileUrl.StartsWith( "http://" ) || lowerFileUrl.StartsWith( "https://" ) )
			{
				//Doc标识为null,表示需要在表单打开时加载Xml文档.
				fileAdapter.Doc = null;
			}
			else if( fileAdapter.FileUrl.StartsWith( "\\\\" ) )
			{
				//在一个网络共享目录中
				fileAdapter.Doc = null;
			}
			else if( fileAdapter.FileUrl.IndexOf( ":\\" ) > 0 )
			{
				//FileUrl是如c:\file.xml的本地文件
				fileAdapter.Doc = null;
			}
			else
			{
				XmlDocument doc = null;
				CABFile cabFile = CABFileFinder.lookupCABFile( manifest, fileUrl );
				if( cabFile == null )
				{
					//可能一些文件如DS.，见Dropdown DS.xsn。
					if( fileUrl.EndsWith( "." ) )
					{
						fileUrl = fileUrl.Substring( 0, fileUrl.Length - 1 );
						cabFile = CABFileFinder.lookupCABFile( manifest, fileUrl );
					}
				}
				if( cabFile == null )
				{	
					doc = new XmlDocument();
				}
				else
				{
					doc = DOMUtil.buildDoc( cabFile.ByteOutput );
				}
				fileAdapter.Doc = doc;
			}
			
			return fileAdapter;
		}

		private static DataSPListAdapter parseSPListAdapter( Manifest manifest, XmlElement spListAdapterElement ){
			string xsfPrefix = manifest.XsfPrefix;
		
			DataSPListAdapter spListAdapter = new DataSPListAdapter();

			spListAdapter.Name = getAdapterName( spListAdapterElement );
			spListAdapter.QueryAllowed = getAdapterQueryAllowed( spListAdapterElement );
			spListAdapter.SubmitAllowed = getAdapterSubmitAllowed( spListAdapterElement );

			string siteUrl = spListAdapterElement.GetAttribute( "siteUrl" );
			if( siteUrl == null || siteUrl.Length <= 0 ){
				throw new InfoJetException("No sharepointListAdapter siteUrl", "XDOP09");
			}
			spListAdapter.SiteUrl = siteUrl;

            
            string guid = spListAdapterElement.GetAttribute( "sharepointGuid" );
            
            if( guid == null || guid.Length <= 0 ){
                throw new InfoJetException("No sharepointListAdapter sharepointGuid", "XDOP10");
            }
            spListAdapter.Guid = guid;
            
			string group = spListAdapterElement.GetAttribute( "infopathGroup" );
			if( group == null || group.Length <= 0 ){
				throw new InfoJetException("No sharepointListAdapter infopathGroup", "XDOP11");
			}
			spListAdapter.Group = XmlConvert.EncodeName( group );

			ArrayList fieldList = new ArrayList();
			XmlNodeList fieldElementList = (XmlNodeList) DOMUtil.selectNodes( spListAdapterElement, NamespaceUtil.toFullName(xsfPrefix, "field"), 0, manifest.NsResolver );
			foreach( XmlElement fieldElement in fieldElementList ){
				DataField field = new DataField();
				string sharepointName = fieldElement.GetAttribute( "sharepointName" );
				if( sharepointName == null || sharepointName.Length <= 0 ){
					throw new InfoJetException("No field sharepointName", "XDOP12");
				}
				field.SharePointName = sharepointName;
				string infopathName = fieldElement.GetAttribute( "infopathName" );
				if( infopathName == null || infopathName.Length <= 0 ){
					throw new InfoJetException("No field infopathName", "XDOP13");
				}
				field.InfoPathName = infopathName;
				fieldList.Add( field );
			}
			spListAdapter.FieldList = fieldList;
				
			return spListAdapter;
		}

        //CID 0703 //2010.12.19 //Begin
        private static char[] UrlSeparator = { '/' };
        //CID 0703 //2010.12.19 //End

        //CID 0703 //2010.12.19 //Begin
        private static DataSPListAdapter parseSPListRWAdapter(Manifest manifest, XmlElement spListAdapterElement)
        {
            string xsfPrefix = manifest.XsfPrefix;

            DataSPListAdapter spListAdapter = new DataSPListAdapter();

            //CID 0703 //2010.12.19 //Begin
            spListAdapter.IsRW = true;
            spListAdapter.Group = "SharePointListItem_RW";
            //CID 0703 //2010.12.19 //End

            spListAdapter.Name = getAdapterName(spListAdapterElement);
            spListAdapter.QueryAllowed = getAdapterQueryAllowed(spListAdapterElement);
            spListAdapter.SubmitAllowed = getAdapterSubmitAllowed(spListAdapterElement);

            string siteUrl = spListAdapterElement.GetAttribute("siteURL");
            if (siteUrl == null || siteUrl.Length <= 0)
            {
                throw new InfoJetException("No sharepointListAdapter siteUrl", "XDOP09RW");
            }
            spListAdapter.SiteUrl = siteUrl;

            //CID 0703 //2010.12.19 //Begin
            if (spListAdapter.SiteUrl.Contains("../") && manifest.RelativeUrlBase != null)
            {
                int count = 0;
                while (siteUrl.IndexOf("../") == 0)
                {
                    siteUrl = siteUrl.Substring(3);
                    count++;
                }
                string url = manifest.RelativeUrlBase;
                for (int i = 0; i <(count + 1); i++)
                {
                    int index = url.LastIndexOf("/");
                    if (index > 0)
                    {
                        url = url.Substring(0, index);
                    }
                    else
                    {
                        throw new InfoJetException("Wrong SPListRW SiteUrl " + spListAdapter.Name, "WrongSPListRWSiteUrl");
                    }
                }
                if (siteUrl.StartsWith("/") || siteUrl.StartsWith("\\"))
                {
                    url = url + siteUrl;
                }
                else
                {
                    url = url + "/" + siteUrl;
                }
                if (!(url.EndsWith("/") || url.EndsWith("\\")))
                {
                    url = url + "/";
                }
                spListAdapter.SiteUrl = url;
            }
            //CID 0703 //2010.12.19 //End

            
            string guid = spListAdapterElement.GetAttribute("sharePointListID");
            
            if (guid == null || guid.Length <= 0)
            {
                throw new InfoJetException("No sharepointListAdapter sharepointGuid", "XDOP10RW");
            }            
            
            spListAdapter.Guid = guid;
            
            ArrayList fieldList = new ArrayList();
            XmlNodeList fieldElementList = (XmlNodeList)DOMUtil.selectNodes(spListAdapterElement, NamespaceUtil.toFullName(xsfPrefix, "field"), 0, manifest.NsResolver);
            foreach (XmlElement fieldElement in fieldElementList)
            {
                DataField field = new DataField();
                string internalName = fieldElement.GetAttribute("internalName");
                if (internalName == null || internalName.Length <= 0)
                {
                    throw new InfoJetException("No field internalName", "XDOP12RW");
                }
                field.SharePointName = internalName;
                field.InfoPathName = internalName;
                fieldList.Add(field);
            }
            spListAdapter.FieldList = fieldList;

            return spListAdapter;
        }
        //CID 0703 //2010.12.19 //End

		public static DataInput parseDataInputInContainer( Manifest manifest, XmlElement operationElement ){
			string xsfPrefix = manifest.XsfPrefix;
			XmlElement inputElement = (XmlElement) DOMUtil.selectANode( operationElement, NamespaceUtil.toFullName(xsfPrefix, "input"), manifest.NsResolver );
			if( inputElement == null ){
				return null;
			}
			DataInput input = new DataInput();
			string source = inputElement.GetAttribute( "source" );
			if( source == null ){
				throw new InfoJetException( "No input source", "XDOP17" );
			}
			input.Source = source;
			input.SourceContent = CABFileFinder.findCABFile( manifest, input.Source ).ByteOutput;
			
			ArrayList partFragList = new ArrayList();
			XmlNodeList partFragElementList = DOMUtil.selectNodes( inputElement, NamespaceUtil.toFullName(xsfPrefix, "partFragment"), 0, manifest.NsResolver );
			foreach( XmlElement partFragElement in partFragElementList ){
				DataPartFragment partFrag = new DataPartFragment();
				string match = partFragElement.GetAttribute( "match" );
				if( match == null || match.Equals( "" ) ){
					throw new InfoJetException( "No partFragment match", "XDOP18" );
				}
				partFrag.Match = match;
				string replaceWith = partFragElement.GetAttribute( "replaceWith" );
				if( replaceWith == null || replaceWith.Equals( "" ) ){
					throw new InfoJetException( "No partFragment replaceWith", "XDOP19" );
				}
				partFrag.ReplaceWith = replaceWith;
				//CID 0229 //2009.02.20 //Begin
				string dataObject = partFragElement.GetAttribute( "dataObject" );
				if( dataObject == null || dataObject.Equals( "" ) )
				{
					dataObject = null;
				}
				//CID 0229 //2009.02.20 //End
				partFrag.DataObject = dataObject;
				partFrag.SendAsString = partFragElement.GetAttribute( "sendAsString" );
				partFrag.Filter = partFragElement.GetAttribute( "filter" );
				partFragList.Add( partFrag );
			}
			input.PartFragmentList = partFragList;
			return input;
		}

		private static string parseSoapPrefix( DataWSAdapter wsAdapter, XmlDocument doc ){
			XmlElement root = doc.DocumentElement;
			foreach( XmlNode childNode in root.ChildNodes ){
				if( childNode is XmlElement ){
					XmlElement element = (XmlElement) childNode;
					if( element.LocalName.Equals( "queryFields" ) ){
						foreach( XmlNode subNode in element.ChildNodes ){
							if( subNode is XmlElement ){
								XmlElement subElement = (XmlElement) subNode;
								if( subElement.LocalName.Equals( wsAdapter.OperationName ) ){
									return subElement.Prefix;
								}
							}
						}
					}
				}
			}
			return "tns";
		}

		private static string getAdapterName( XmlElement adapterElement )
		{
			return adapterElement.GetAttribute( "name" );
		}

		private static bool getAdapterQueryAllowed( XmlElement adapterElement )
		{
			string queryAllowed = adapterElement.GetAttribute( "queryAllowed" );
			if( queryAllowed != null && queryAllowed.Equals( "yes" ) )
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		private static bool getAdapterSubmitAllowed( XmlElement adapterElement )
		{
			string submitAllowed = adapterElement.GetAttribute( "submitAllowed" );
			if( submitAllowed != null && submitAllowed.Equals( "yes" ) )
			{
				return true;
			}
			else
			{
				return false;
			}
		}

	}
}